package com.information.manage.basic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.information.manage.basic.common.utils.RedisUtils;
import com.information.manage.basic.model.dto.DepartmentExportDTO;
import com.information.manage.basic.model.dto.DepartmentImportDTO;
import com.information.manage.basic.model.dto.DepartmentImportResultDTO;
import com.information.manage.basic.model.dto.DepartmentLeadingDTO;
import com.information.manage.basic.model.entity.DepartmentDO;
import com.information.manage.basic.model.entity.StaffDO;
import com.information.manage.basic.model.entity.StaffDetailDO;
import com.information.manage.basic.model.query.DepartmentAddQuery;
import com.information.manage.basic.model.query.DepartmentFindByConditionQuery;
import com.information.manage.basic.model.query.DepartmentUpdateQuery;
import com.information.manage.basic.model.vo.DepartmentListVO;
import com.information.manage.basic.model.vo.DepartmentTreeVO;
import com.information.manage.basic.common.constant.Constant;
import com.information.manage.basic.common.recycling.RecoveryDataOperateManager;
import com.information.manage.basic.common.result.Result;
import com.information.manage.basic.mapper.DepLeaderMapper;
import com.information.manage.basic.mapper.DepartmentMapper;
import com.information.manage.basic.mapper.StaffDetailMapper;
import com.information.manage.basic.mapper.StaffMapper;
import com.information.manage.basic.model.entity.DepLeaderDO;
import com.information.manage.basic.service.DepartmentService;
import com.information.manage.basic.common.constant.TypeCollectionEnum;
import com.information.manage.basic.common.utils.exportAndImport.ExcelUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sy
 * @since 2021-12-27
 */
@Slf4j
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, DepartmentDO> implements DepartmentService {

    @Resource
    private DepartmentMapper departmentMapper;

    @Resource
    private RecoveryDataOperateManager recoveryDataManager;

    @Resource
    private DepLeaderMapper depLeaderMapper;

    @Resource
    private StaffMapper staffMapper;

    @Resource
    private StaffDetailMapper staffDetailMapper;

    @Resource
    private RedisUtils redisUtils;

    private static final String departmentCacheKey = "department_info";

    private static final String depClassifyKey = "dep_classify";

    // 修改部门后需要移除对应的key，用到的地方才能重新获取，保证数据一致性
    private void removeRedisKey(){
        redisUtils.remove(departmentCacheKey, depClassifyKey);
    }

    @Override
    public Result<Integer> addDepartment(DepartmentAddQuery departmentAddQuery) {
        Integer parentId = -1; //定义父id
        //判断父id是否存在
        if (departmentAddQuery.getParentId() != null && !parentId.equals(departmentAddQuery.getParentId())) {
            Integer countByParentId = departmentMapper.selectCount(new LambdaQueryWrapper<DepartmentDO>()
                    .eq(DepartmentDO::getId, departmentAddQuery.getParentId())
                    .eq(DepartmentDO::getTypeCollection, departmentAddQuery.getTypeCollection()));
            if (countByParentId == 0) return Result.fail("上级部门不存在");
        }else {  //设置默认值父id为-1
            departmentAddQuery.setParentId(parentId);
        }
        //判断当前父id下是否存在该部门
        if (departmentMapper.selectCount(new LambdaQueryWrapper<DepartmentDO>()
            .eq(DepartmentDO::getName, departmentAddQuery.getDepartmentName())
            .eq(DepartmentDO::getParentId, departmentAddQuery.getParentId())
            .eq(DepartmentDO::getTypeCollection, departmentAddQuery.getTypeCollection())) != 0) return Result.fail("部门已存在");
        DepartmentDO departmentDO = new DepartmentDO();
        departmentDO.setParentId(departmentAddQuery.getParentId());
        departmentDO.setName(departmentAddQuery.getDepartmentName());
        departmentDO.setDescription(departmentAddQuery.getDescription() == null ? "" : departmentAddQuery.getDescription());
        //获取已有的排序
        Integer maxOrder = departmentMapper.queryMaxOrderByParentId(departmentAddQuery.getParentId(), departmentAddQuery.getTypeCollection());
        //当排序存在时+1 不存在时设置为1
        if (maxOrder != null) departmentDO.setSequence(++maxOrder);
        else departmentDO.setSequence(1);
        //添加部门类型集
        departmentDO.setTypeCollection(departmentAddQuery.getTypeCollection());
        departmentMapper.insert(departmentDO);
        //保存部门负责人
        if (departmentAddQuery.getLeadingStaffId() != null){
            DepLeaderDO depLeaderDO = new DepLeaderDO();
            depLeaderDO.setDepartmentId(departmentDO.getId());
            depLeaderDO.setLeaderId(departmentAddQuery.getLeadingStaffId());
            depLeaderMapper.insert(depLeaderDO);
        }
        removeRedisKey();
        return Result.ok(departmentDO.getId());
    }

    @Override
    public Result<Integer> updateDepartment(DepartmentUpdateQuery departmentUpdateQuery) {
        Integer parentId = -1; //定义父id
        DepartmentDO departmentDO = departmentMapper.selectById(departmentUpdateQuery.getId());
        //接受到的值不包含父id时设置默认值为-1
        if (departmentUpdateQuery.getParentId() == null || parentId.equals(departmentUpdateQuery.getParentId())){
            departmentUpdateQuery.setParentId(parentId);
        } else {  // 判断存在性
            Integer countByParentId = departmentMapper.selectCount(new LambdaQueryWrapper<DepartmentDO>()
                    .eq(DepartmentDO::getId, departmentUpdateQuery.getParentId())
                    .eq(DepartmentDO::getTypeCollection, departmentDO.getTypeCollection()));
            if (countByParentId == 0) return Result.fail("上级部门不存在");
        }
        //保存部门负责人
        if (departmentUpdateQuery.getLeadingStaffId() != null){
            Integer count = depLeaderMapper.selectCount(new LambdaQueryWrapper<DepLeaderDO>()
                    .eq(DepLeaderDO::getDepartmentId, departmentUpdateQuery.getId()));
            if (count != 0) {  //已存在部门负责人 修改
                depLeaderMapper.update(null, new LambdaUpdateWrapper<DepLeaderDO>()
                        .eq(DepLeaderDO::getDepartmentId, departmentUpdateQuery.getId())
                        .set(DepLeaderDO::getLeaderId,  departmentUpdateQuery.getLeadingStaffId()));
            }else { //不存在部门负责人 添加
                DepLeaderDO depLeaderDO = new DepLeaderDO();
                depLeaderDO.setDepartmentId(departmentUpdateQuery.getId());
                depLeaderDO.setLeaderId(departmentUpdateQuery.getLeadingStaffId());
                depLeaderMapper.insert(depLeaderDO);
            }
        }
        //判断当前父id下是否存在该部门
        if (departmentMapper.selectCount(new LambdaQueryWrapper<DepartmentDO>()
                .eq(DepartmentDO::getName, departmentUpdateQuery.getDepartmentName())
                .eq(DepartmentDO::getParentId, departmentUpdateQuery.getParentId())
                .ne(DepartmentDO::getId, departmentUpdateQuery.getId())
                .eq(DepartmentDO::getTypeCollection, departmentDO.getTypeCollection())) != 0) {
            return Result.fail("部门已存在");
        }else {
            departmentDO.setParentId(departmentUpdateQuery.getParentId());
            departmentDO.setName(departmentUpdateQuery.getDepartmentName() == null || "".equals(departmentUpdateQuery.getDepartmentName().trim())
                    ? null : departmentUpdateQuery.getDepartmentName());
            departmentDO.setDescription(departmentUpdateQuery.getDescription() == null || "".equals(departmentUpdateQuery.getDescription().trim())
                    ? null : departmentUpdateQuery.getDescription());
            departmentMapper.updateById(departmentDO);
            removeRedisKey();
            return Result.ok(departmentDO.getId());
        }
    }


    @Override
  //  @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> deleteDepartment(List<Integer> departmentIds) {
        try {
            recoveryDataManager.deleteData(DepartmentDO.class, departmentIds);
            removeRedisKey();
            return Result.ok(true);
        }catch (Exception e){
            log.info("删除部门失败", e);
            return Result.ok(false);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean moveDepartment(Integer id, boolean up) {
        //获取当前层级的数据
        DepartmentDO curData = departmentMapper.selectById(id);
        int order;
        //当层级不存在时 不能上移
        if (curData.getSequence() == null) return false;
        if (up){ //上移
            //获取上一层级
            order = curData.getSequence() - 1;
        }else { //下移
            //获取下一层级
            order = curData.getSequence() + 1;
        }
        DepartmentDO upOrDownData = departmentMapper.selectOne(new LambdaQueryWrapper<DepartmentDO>()
                .eq(DepartmentDO::getParentId, curData.getParentId())
                .eq(DepartmentDO::getSequence, order)
                .eq(DepartmentDO::getTypeCollection, curData.getTypeCollection())
                .orderByDesc(DepartmentDO::getId).last("limit 1"));
        //上移时不存在上一层级 下移时不存在下一层级  不能移动
        if (upOrDownData == null || upOrDownData.getSequence() == null) return false;
        //调换排序数据 order 更新
        //tmp 临时存储
        int tmp;
        tmp = curData.getSequence();
        curData.setSequence(upOrDownData.getSequence());
        int cur = departmentMapper.updateById(curData);
        if (cur == 0) throw new RuntimeException("移动部门出错");
        upOrDownData.setSequence(tmp);
        int update = departmentMapper.updateById(upOrDownData);
        if (update == 0) throw new RuntimeException("移动部门出错");
        removeRedisKey();
        return true;
    }

    @Override
    public String queryDepartmentNameById(Integer id) {
        Map<Integer, String> map = generateParentAndChildDepartment(Arrays.asList(id));
        return map.get(id);
    }

    @Override
    public Map<Integer, String> queryDepartmentNameById(List<Integer> id) {
        Map<Integer, String> map = generateParentAndChildDepartment(id);
        return map;
    }

    @Override
    public List<Integer> getIdsByTypeCollection(Long typeCollection) {
        List<DepartmentDO> departmentDOS = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getTypeCollection, typeCollection));
        return departmentDOS.stream().map(DepartmentDO::getId).collect(Collectors.toList());
    }

    @Override
    public List<DepartmentListVO> queryDepartmentListById(Integer id) {
        //设置父id默认值
        if (id == null) id = -1;
        List<DepartmentListVO> departmentListVOS = departmentMapper.queryDepartmentListById(id);
        List<Integer> departmentIds = departmentListVOS.stream().map(it -> it.getId()).collect(Collectors.toList());
        try {
            Map<Integer, DepartmentLeadingDTO> map = this.getLeadingStaff(departmentIds);
            for (DepartmentListVO departmentListVO : departmentListVOS) {
                DepartmentLeadingDTO departmentLeadingDTO = map.get(departmentListVO.getId());
                departmentListVO.setLeadingStaff(departmentLeadingDTO.getLeadingName());
                departmentListVO.setLeadingId(departmentLeadingDTO.getLeadingId());
            }
        }catch (Exception e){
            log.info("获取部门负责人失败");
        }
        return departmentListVOS;
    }

    private Map<Integer, DepartmentLeadingDTO> getLeadingStaff(List<Integer> departmentIds) {
        Map<Integer, DepartmentLeadingDTO> map = new HashMap<>();
        List<DepLeaderDO> depLeaderDOS = depLeaderMapper.selectList(new LambdaQueryWrapper<DepLeaderDO>().in(DepLeaderDO::getDepartmentId, departmentIds));
        if(depLeaderDOS.size() > 0){
            // 部门id -》 员工id
            Map<Integer, Integer> collect = depLeaderDOS.stream().collect(Collectors.toMap(it -> it.getDepartmentId(), it -> it.getLeaderId()));
            // 获取所有的领导人id
            List<Integer> staffIds = depLeaderDOS.stream().map(it -> it.getLeaderId()).collect(Collectors.toList());
            // 员工id -》 员工姓名
            Map<Integer, String> staffInfo = staffMapper.selectList(new LambdaQueryWrapper<StaffDO>()
                    .in(StaffDO::getId, staffIds)).stream().collect(Collectors.toMap(it -> it.getId(), it -> it.getName()));
            for (Integer departmentId : departmentIds) {
                DepartmentLeadingDTO departmentLeadingDTO = new DepartmentLeadingDTO();
                Integer leadingId = collect.get(departmentId);
                departmentLeadingDTO.setLeadingId(Long.valueOf(leadingId));
                departmentLeadingDTO.setLeadingName(staffInfo.get(leadingId));
                map.put(departmentId, departmentLeadingDTO);
            }
        }
        return map;
    }

    @Override
    public List<DepartmentTreeVO> queryDepartmentByCondition(DepartmentFindByConditionQuery departmentFindByConditionQuery) {
        List<DepartmentDO> departmentDOList = departmentMapper.queryDepartmentListByName(departmentFindByConditionQuery.getDepartmentName(), departmentFindByConditionQuery.getTypeCollection());
        List<Integer> ids = departmentDOList.stream().map(it -> it.getId()).collect(Collectors.toList());
        return this.getDepartmentTreeByIds(ids);
    }

    /**
     * 设置部门树中的负责人
     * @param departmentTreeVOList 部门树 集合
     */
    private void setTreeLeadingStaff(List<DepartmentTreeVO> departmentTreeVOList){
        //保存部门id
        List<Integer> departmentIds = new ArrayList<>();
        //获取该集合中所有的部门id
        getDepartmentIds(departmentTreeVOList, departmentIds);
        try {
            Map<Integer, DepartmentLeadingDTO> leadingStaff = this.getLeadingStaff(departmentIds);
            setDepartmentName(departmentTreeVOList, leadingStaff);
        }catch (Exception e){
            log.info("获取部门负责人失败");
        }
    }

    /**
     * 获取递归集合中的所有部门id
     * @param list 递归数据的集合
     * @param departmentIds 保存部门id的集合
     */
    private void getDepartmentIds(List<DepartmentTreeVO> list, List<Integer> departmentIds){
        for (DepartmentTreeVO departmentTreeVO : list) {
            departmentIds.add(departmentTreeVO.getId());
            if (departmentTreeVO.getDepartmentTreeVOList() != null && departmentTreeVO.getDepartmentTreeVOList().size() > 0){
                getDepartmentIds(departmentTreeVO.getDepartmentTreeVOList(), departmentIds);
            }
        }
    }

    /**
     * 设置集合中的部门名称
     * @param list
     * @param map
     */
    private void setDepartmentName(List<DepartmentTreeVO> list, Map<Integer, DepartmentLeadingDTO> map){
        for (DepartmentTreeVO departmentTreeVO : list) {
            DepartmentLeadingDTO departmentLeadingDTO = map.get(departmentTreeVO.getId());
            departmentTreeVO.setLeadingStaff(departmentLeadingDTO.getLeadingName());
            departmentTreeVO.setLeadingId(departmentLeadingDTO.getLeadingId());
            if (departmentTreeVO.getDepartmentTreeVOList() != null && departmentTreeVO.getDepartmentTreeVOList().size() > 0){
                setDepartmentName(departmentTreeVO.getDepartmentTreeVOList(), map);
            }
        }
    }

    /**
     * 递归获取部门数据
     * @param map 部门map id -> 部门数据
     * @param departmentDO 当前部门数据
     * @return
     */
    private List<DepartmentTreeVO> recursionAdd(Map<Integer, DepartmentDO> map, DepartmentDO departmentDO){
        List<DepartmentTreeVO> list = new ArrayList<>();
        List<DepartmentTreeVO> child = new ArrayList<>();
        DepartmentTreeVO departmentTreeVO = new DepartmentTreeVO();
        departmentTreeVO.setId(departmentDO.getId());
        departmentTreeVO.setName(departmentDO.getName());
        departmentTreeVO.setSequence(departmentDO.getSequence());
        departmentTreeVO.setParentId(departmentDO.getParentId());
        departmentTreeVO.setDescription(departmentDO.getDescription());
        for (Integer key : map.keySet()) {
            if (departmentDO.getId().equals(map.get(key).getParentId())){
                child.addAll(recursionAdd(map, map.get(key)));
            }
        }
        //子部门存在时按层级排序
        if (child.size() > 0){
            Collections.sort(child, new Comparator<DepartmentTreeVO>() {
                @Override
                public int compare(DepartmentTreeVO o1, DepartmentTreeVO o2) {
                    return o1.getSequence().compareTo(o2.getSequence());
                }
            });
            departmentTreeVO.setDepartmentTreeVOList(child);
        }
        list.add(departmentTreeVO);
        return list;
    }

    /**
     * 排序部门数最外层的层级
     * @param departmentTreeVOList
     */
    private void outerMostSort(List<DepartmentTreeVO> departmentTreeVOList) {
        //最外层排序层级
        Collections.sort(departmentTreeVOList, new Comparator<DepartmentTreeVO>() {
            @Override
            public int compare(DepartmentTreeVO o1, DepartmentTreeVO o2) {
                return o1.getSequence().compareTo(o2.getSequence());
            }
        });

    }

    @Override
    public List<DepartmentTreeVO> getDepartmentTreeByIds(List<Integer> departmentIds) {
        List<DepartmentTreeVO> departmentTreeVOList = new ArrayList<>();
        // id -> 部门数据
        Map<Integer, DepartmentDO> map = getDepartmentAndParent(departmentIds);
        Integer pid = -1;
        for (Integer key : map.keySet()) {
            if (pid.equals(map.get(key).getParentId())){   //递归获取， 从顶层部门开始
                departmentTreeVOList.addAll(recursionAdd(map, map.get(key)));
            }
        }
        //层级排序最外层
        outerMostSort(departmentTreeVOList);
        //设置部门树中的负责人
        setTreeLeadingStaff(departmentTreeVOList);
        return departmentTreeVOList;
    }

    @Override
    public void downloadExcel(HttpServletResponse response) {
        ExcelUtils.downloadExcelTemplate(response, "/static/basic/department.xls");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result excelImport(HttpServletResponse response, MultipartFile file) {
        List<DepartmentImportResultDTO> resultDTOList = new ArrayList<>();
        List<DepartmentImportDTO> departmentImportDTOList = ExcelUtils.importExcel(file, 0, 1, DepartmentImportDTO.class);
        for (DepartmentImportDTO departmentImportDTO : departmentImportDTOList) {
            String departmentName = departmentImportDTO.getDepartmentName();
            //去除起始位的“/”
            if (departmentName.startsWith("/")) departmentName = departmentName.substring(1);
            int end = departmentName.indexOf("/");
            //定义中间变量 用于保存部门链 存储去除部门链中的第一个部门的数据
            String surplus = departmentName;
            int pid = -1;
            //先从父部门开始 若父部门不存在，先创建   最后比较子部门 若存在则提示错误 不存在则添加
            while (end != -1){
                surplus = surplus.substring(end + 1);
                departmentName = departmentName.substring(0, end);
                //获取父部门信息
                DepartmentDO departmentDO = departmentMapper.selectOne(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getParentId, pid).eq(DepartmentDO::getName, departmentName));
                if (departmentDO == null){ //父部门不存在， 创建
                    resultDTOList.add(establishDepartment(departmentName, pid, departmentImportDTO));
                }else {
                    //修改父id值 用于子部门添加
                    pid = departmentDO.getId();
                }
                end = surplus.indexOf("/");
                departmentName = surplus;
            }
            //最后的部门名称
            String childDepartment = departmentName.substring(departmentName.lastIndexOf("/") + 1);
            Integer count = departmentMapper.selectCount(new LambdaQueryWrapper<DepartmentDO>().eq(DepartmentDO::getParentId, pid).eq(DepartmentDO::getName, childDepartment));
            if (count != 0){ //部门已经存在
                //添加返回结果集 处理失败
                resultDTOList.add(DepartmentImportResultDTO.builder().departmentName(departmentName).status(Constant.FAIL).reason("部门已存在").build());
            }else { //创建
                DepartmentImportResultDTO departmentImportResultDTO = establishDepartment(departmentName, pid, departmentImportDTO);
                resultDTOList.add(departmentImportResultDTO);
                //获取部门负责人id
                Integer staffId;
                List<StaffDO> staffDOList = staffMapper.selectList(new LambdaQueryWrapper<StaffDO>()
                        .select(StaffDO::getStaffDetailId).select(StaffDO::getId)
                        .eq(StaffDO::getJobNumber, departmentImportDTO.getLeadingStaffJobNumber()));
                if (staffDOList.size() == 0) {
                    staffId = null;
                }else if (staffDOList.size() == 1){
                    staffId = staffDOList.get(0).getId();
                }else {
                    //多个员工共用工号时，取在职的员工
                    //detailId -> id
                    Map<Integer, Integer> map = staffDOList.stream().collect(Collectors.toMap(it -> it.getStaffDetailId(), it -> it.getId()));
                    Integer detailId = (Integer) staffDetailMapper.selectObjs(new LambdaQueryWrapper<StaffDetailDO>()
                            .select(StaffDetailDO::getId)
                            .in(StaffDetailDO::getId, map.keySet())
                            .eq(StaffDetailDO::getState, 0)) //todo 未退休状态字典id
                            .stream().findFirst().orElse(null);
                    if (detailId != null) staffId = map.get(detailId);
                    else staffId = null;
                }
                //添加负责人
                DepLeaderDO depLeaderDO = new DepLeaderDO();
                depLeaderDO.setDepartmentId(departmentImportResultDTO.getDepartmentId());
                depLeaderDO.setLeaderId(staffId);
                depLeaderMapper.insert(depLeaderDO);
            }
        }
        removeRedisKey();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm");
        String format = simpleDateFormat.format(new Date());
        // 导出结果
        ExcelUtils.exportExcel(resultDTOList, null, "sheet1", DepartmentImportResultDTO.class, format + "部门导入结果" + ".xls", response);
        return Result.ok();
    }

    /**
     * 创建部门
     * @param departmentName
     * @param pid
     * @param departmentImportDTO
     * @return
     */
    private DepartmentImportResultDTO establishDepartment(String departmentName, Integer pid, DepartmentImportDTO departmentImportDTO){
        String childDepartment = departmentName.substring(departmentName.lastIndexOf("/") + 1);
        DepartmentDO departmentDO = new DepartmentDO();
        departmentDO.setName(childDepartment);
        departmentDO.setParentId(pid);
        departmentDO.setDescription(departmentImportDTO.getDescription());
        departmentDO.setTypeCollection(TypeCollectionEnum.DEPARTMENT.code);  //部门类型 0x01
        Integer maxSequence = departmentMapper.queryMaxOrderByParentId(pid, TypeCollectionEnum.DEPARTMENT.code);
        if (maxSequence == null) departmentDO.setSequence(1); //层级不存在时，设置为第一层
        else departmentDO.setSequence(++maxSequence);
        int resultCount = departmentMapper.insert(departmentDO);
        //大于0时添加返回结果集 处理成功  否则返回处理失败
        if (resultCount > 0) return DepartmentImportResultDTO.builder().departmentId(departmentDO.getId()).departmentName(departmentName).status(Constant.SUCCESS).build();
        else return DepartmentImportResultDTO.builder().departmentId(departmentDO.getId()).departmentName(departmentName).status(Constant.FAIL).reason("处理错误").build();
    }

    @Override
    public void exportExcel(HttpServletResponse response, Long typeCollection, String departmentName) {
        List<DepartmentDO> departmentDOList = new ArrayList<>();
        DepartmentFindByConditionQuery departmentFindByConditionQuery = new DepartmentFindByConditionQuery();
        departmentFindByConditionQuery.setDepartmentName(departmentName);
        departmentFindByConditionQuery.setTypeCollection(typeCollection);
        List<DepartmentTreeVO> departmentTreeVOList = queryDepartmentByCondition(departmentFindByConditionQuery);
        //存放部门和负责人
        Map<Integer, String> idAndLeadingStaffMap = departmentTreeVOList.stream().collect(Collectors.toMap(it -> it.getId()
                , it -> StringUtils.isNotEmpty(it.getLeadingStaff()) ? it.getLeadingStaff() : StringUtils.EMPTY));
        //解析出满足添加的的部门数据
        departmentDOList = recursionParas(departmentTreeVOList, departmentDOList);
        List<DepartmentExportDTO> exportDTOList = new ArrayList<>();
        List<Integer> departmentIds = departmentDOList.stream().map(it -> it.getId()).collect(Collectors.toList());
        Map<Integer, String> map = generateParentAndChildDepartment(departmentIds);
        for (DepartmentDO departmentDO : departmentDOList) {
            for (Integer key : map.keySet()) {  //添加导出的部门数据
                if (departmentDO.getId().equals(key)){
                    DepartmentExportDTO departmentExportDTO = new DepartmentExportDTO();
                    departmentExportDTO.setDepartmentName(map.get(key));
                    departmentExportDTO.setLeadingStaff(idAndLeadingStaffMap.get(key));
                    departmentExportDTO.setDescription(departmentDO.getDescription());
                    exportDTOList.add(departmentExportDTO);
                    // 相同的部门只会出现一次 停止本次循环
                    continue;
                }
            }
        }
        ExcelUtils.exportExcel(exportDTOList, null, "sheet1", DepartmentExportDTO.class, "部门数据.xls", response);
    }

    /**
     * 递归解析部门数据
     * @param departmentTreeVOList 递归查询的结果
     * @param departmentDOList 返回的结果值
     * @return
     */
    private List<DepartmentDO> recursionParas(List<DepartmentTreeVO> departmentTreeVOList, List<DepartmentDO> departmentDOList){
        for (DepartmentTreeVO departmentTreeVO : departmentTreeVOList) {
            DepartmentDO departmentDO = new DepartmentDO();
            departmentDO.setId(departmentTreeVO.getId());
            departmentDO.setName(departmentTreeVO.getName());
            departmentDO.setSequence(departmentTreeVO.getSequence());
            departmentDO.setDescription(departmentTreeVO.getDescription());
            departmentDOList.add(departmentDO);
            if (departmentTreeVO.getDepartmentTreeVOList() != null && departmentTreeVO.getDepartmentTreeVOList().size() > 0){
                recursionParas(departmentTreeVO.getDepartmentTreeVOList(), departmentDOList);
            }
        }
        return departmentDOList;
    }

    /**
     * 获取部门及其父部门信息
     * @param departmentIds 子部门id
     * @return
     */
    protected Map<Integer, DepartmentDO> getDepartmentAndParent(List<Integer> departmentIds){
        List<Integer> ids = new ArrayList<>();
        ids.addAll(departmentIds);
        Map<Integer, DepartmentDO> map = new HashMap<>();
        while(ids.size() > 0){
            List<DepartmentDO> DepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>()
                    .in(DepartmentDO::getId, ids));
            ids.clear();
            // 筛选区域
            for (DepartmentDO departmentDO : DepartmentList) {
                if(!map.containsKey(departmentDO.getId())){
                    // 不包含
                    map.put(departmentDO.getId(), departmentDO);
                }
                if(-1 != departmentDO.getParentId() && !map.containsKey(departmentDO.getParentId())){
                    // 父区域不在map中
                    if(!ids.contains(departmentDO.getParentId())){
                        ids.add(departmentDO.getParentId());
                    }
                }
            }
        }
        return map;
    }

    /**
     * 生成部门结果集
     * @param ids 子部门id
     * @return  id -》 完整部门路径
     */
    @Override
    public Map<Integer, String> generateParentAndChildDepartment(List<Integer> ids){
        //获取父子部门集合
        Map<Integer, DepartmentDO> regionAndParentMap = this.getDepartmentAndParent(ids);
        StringBuilder sb = new StringBuilder();
        List<DepartmentDO> departmentDOList = new ArrayList<>();
        Map<Integer, String> map = new HashMap<>();
        //组装部门
        for (Integer id : ids) {
            sb.delete(0, sb.length());
            departmentDOList.clear();
            DepartmentDO dto = regionAndParentMap.get(id);
            if(dto != null){
                while(dto != null){
                    departmentDOList.add(dto);
                    dto = regionAndParentMap.get(dto.getParentId());
                }
                //拼装父子部门
                for(int i = departmentDOList.size() - 1; i > 0; i--){
                    sb.append(departmentDOList.get(i).getName());
                    sb.append("/");
                }
                sb.append(departmentDOList.get(0).getName());
                map.put(id, sb.toString());
            }
        }
        return map;
    }

    /**
     * 根据部门id获取其所有部门（自身+父部门）
     * list 中存放顺序： 父部门 -》 子部门
     * @param departmentId
     * @return
     */
    @Override
    public List<String> getParentDepartmentListById(Integer departmentId){
        List<String> departmentNameList = new ArrayList<>();
        Map<Integer, String> map = generateParentAndChildDepartment(Arrays.asList(departmentId));
        String complete = map.get(departmentId);
        if (complete != null && !"".equals(complete)){
            int index = complete.indexOf("/");
            while (index != -1){
                departmentNameList.add(complete.substring(0, index));
                complete = complete.substring(index + 1);
                index = complete.indexOf("/");
            }
            departmentNameList.add(complete);
        }
        return departmentNameList;
    }

    /**
     * 根据部门id查询所有的子部门id
     * @param departmentId
     * @return  当前部门id及其子部门id
     */
    @Override
    public List<Integer> getDepartmentAndChildId(Integer departmentId){
        if (departmentId == null) return Collections.EMPTY_LIST;
        List<Integer> list = new ArrayList<>();
        List<DepartmentDO> departmentDOList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>());
        //id -> 部门信息
        Map<Integer, DepartmentDO> map = departmentDOList.stream().collect(Collectors.toMap(it -> it.getId(), it -> it));
        List<Integer> parentIds = departmentDOList.stream().map(it -> it.getParentId()).collect(Collectors.toList());
        list.add(departmentId);
        recursionGetChild(map, departmentId, list, parentIds);
        return list;
    }

    /**
     * 递归获取子部门
     * @param map 所有的部门map  id -》 部门信息
     * @param departmentId 当前部门
     * @param list 存放返回结果的list
     * @param parentIds 所有部门的父id
     */
    private void recursionGetChild(Map<Integer, DepartmentDO> map, Integer departmentId, List<Integer> list, List<Integer> parentIds){
        for (Integer key : map.keySet()) {
            if (departmentId.equals(map.get(key).getParentId())){
                //添加子部门id
                Integer id = map.get(key).getId();
                list.add(id);
                if (parentIds.contains(id)){
                    recursionGetChild(map, id, list, parentIds);
                }
            }
        }
    }

    /**
     * 通过部门完整路径获取部门id
     * @param departmentName
     * @return 部门id
     */
    @Override
    public Integer getDepartmentIdByName(String departmentName){
        List<Integer> ids = departmentMapper.selectObjs(new LambdaQueryWrapper<DepartmentDO>()
                .select(DepartmentDO::getId)).stream().map(it -> (Integer) it).collect(Collectors.toList());
        Map<Integer, String> map = generateParentAndChildDepartment(ids);
        for (Integer key : map.keySet()) {
            if (departmentName.equals(map.get(key))){
                return key;
            }
        }
        return null;
    }

    @Override
    public List<DepartmentTreeVO> getDepartmentTreeByParentIds(List<Integer> departmentIds) {
        Integer pid = -1;
        //筛选出顶层部门
        departmentIds = departmentMapper.selectObjs(new LambdaQueryWrapper<DepartmentDO>()
                .in(DepartmentDO::getId, departmentIds).eq(DepartmentDO::getParentId, pid))
                .stream().map(it -> (Integer) it).collect(Collectors.toList());
        List<DepartmentTreeVO> departmentTreeVOList = new ArrayList<>();
        // id -> 部门数据
        Map<Integer, DepartmentDO> map = getDepartmentAndChildMap(departmentIds);
        for (Integer key : map.keySet()) {
            if (pid.equals(map.get(key).getParentId())){   //递归获取， 从顶层部门开始
                departmentTreeVOList.addAll(recursionAdd(map, map.get(key)));
            }
        }
        //层级排序最外层
        outerMostSort(departmentTreeVOList);
        //设置部门树中的负责人
        setTreeLeadingStaff(departmentTreeVOList);
        return departmentTreeVOList;
    }

    /**
     * 获取部门及其子部门信息
     * @param departmentIds  父部门id
     * @return map id -> 部门信息
     */
    protected Map<Integer, DepartmentDO> getDepartmentAndChildMap(List<Integer> departmentIds){
        //获取所有的部门信息
        List<DepartmentDO> allDepartmentList = departmentMapper.selectList(new LambdaQueryWrapper<DepartmentDO>());
        List<Integer> ids = new ArrayList<>();
        ids.addAll(departmentIds);
        Map<Integer, DepartmentDO> map = new HashMap<>();
        while(ids.size() > 0){
            //获取当前部门信息
            List<DepartmentDO> departmentDOList = allDepartmentList.stream().filter(it -> ids.contains(it.getId())).collect(Collectors.toList());
            ids.clear();
            // 筛选区域
            for (DepartmentDO departmentDO : departmentDOList) {
                if(!map.containsKey(departmentDO.getId())){ // 不包含
                    map.put(departmentDO.getId(), departmentDO);
                }
                this.recursionGetChild(allDepartmentList, map, departmentDO.getId());
            }
        }
        return map;
    }

    /**
     * 递归获取子部门
     * @param departmentDOList 所有的部门集合
     * @param map 需要返回的map  id -》 部门信息  包含添加从curId后的所有子部门
     * @param curId 当前部门id
     */
    private void recursionGetChild(List<DepartmentDO> departmentDOList, Map<Integer, DepartmentDO> map, Integer curId){
        //获取子部门信息
        List<DepartmentDO> children = departmentDOList.stream().filter(it -> it.getParentId() == curId).collect(Collectors.toList());
        if (children.size() > 0){
            for (DepartmentDO child : children) {
                if(!map.containsKey(child.getId())){ // 不包含
                    map.put(child.getId(), child);
                }
                int size = departmentDOList.stream().filter(it -> it.getParentId() == child.getId()).collect(Collectors.toList()).size();
                if (size > 0){
                    this.recursionGetChild(departmentDOList, map, child.getId());
                }
            }
        }
    }

}
